package com.yqg.protection.netty.handler;

import com.yqg.protection.netty.service.KeAn4040Service;
import com.yqg.protection.utils.ByteUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.ReferenceCountUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

@Component
@Slf4j
@ChannelHandler.Sharable
public class KeAn4040Handler extends AbstractProtocolHandler implements DynamicProtocolHandler {

    @Autowired
    private KeAn4040Service keAn4040Service;

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        try {
            if (msg instanceof ByteBuf) {
                ByteBuf buf = (ByteBuf) msg;
                // 将ByteBuf转换为十六进制字符串
                String hexData = ByteBufUtil.hexDump(buf).toUpperCase();
                log.info("收到4040原始数据: {}", hexData);

                // 创建ProtocolData对象
                ProtocolData protocolData = new ProtocolData();
                protocolData.setHeader(hexData.substring(0,4));
                protocolData.setRawData(hexData);
                protocolData.setCtx(ctx);
                protocolData.setSaveTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));

                // 生成并发送响应
                byte[] response = generateResponse(protocolData);
                ctx.writeAndFlush(Unpooled.wrappedBuffer(response));
                log.info("已发送4040协议响应");

                // 调用处理逻辑
                handle(protocolData);
            } else {
                log.warn("收到非ByteBuf类型数据: {}", msg.getClass().getName());
                ctx.fireChannelRead(msg);
            }
        } finally {
            ReferenceCountUtil.release(msg);
        }
    }

    public void handle(ProtocolData data) {
        String raw = data.getRawData();
        // 解析公共字段
        String flow = raw.substring(4, 8);
        String version = raw.substring(8, 12);
        String time = raw.substring(12, 24);
        String src = raw.substring(24, 36);
        // 转换时间格式
        String sendTime = keAn4040Service.formatTime(time);

        // 异步处理
        executor.execute(() -> dataSaver.saveDataToFileAsync(raw, sendTime, src));
        executor.execute(() -> keAn4040Service.analyzeDataUnits(flow, sendTime, raw.substring(54, raw.length() - 6), src));

    }

    public byte[] generateResponse(ProtocolData data) {
        String raw = data.getRawData();
        String header = data.getHeader();
        String flow = raw.substring(4, 8);
        String version = raw.substring(8, 12);
        String src = raw.substring(24, 36);
        String mudi = raw.substring(36, 48);
        String end = raw.substring(raw.length() - 4);
        return checksumUser(header, flow, version, src, mudi, end);
    }

    @Override
    public String supportHeader() {
        return "4040";
    }

    /**
     * 校验和用户
     *
     * @param headed  领导
     * @param flowId  流id
     * @param version 版本
     * @param src     src
     * @param mu
     * @param end     结束
     * @return {@link byte[]}
     */
    public byte[] checksumUser(String headed, String flowId, String version, String src, String mu, String end) {

        Integer f1 = Integer.parseInt(flowId.substring(0, 2), 16);
        Integer f2 = Integer.parseInt(flowId.substring(2), 16);
        Integer vma = Integer.parseInt(version.substring(0, 2), 16);
        Integer vmi = Integer.parseInt(version.substring(2), 16);
        //同步心跳包时间
        Calendar now = Calendar.getInstance();
        Integer year = now.get(Calendar.YEAR) - 2000;
        String hex_year = ByteUtil.buqi3(Integer.toHexString(year));
        Integer month = (now.get(Calendar.MONTH) + 1);
        String hex_month = ByteUtil.buqi3(Integer.toHexString(month));
        Integer day = now.get(Calendar.DAY_OF_MONTH);
        String hex_day = ByteUtil.buqi3(Integer.toHexString(day));
        Integer hour = now.get(Calendar.HOUR_OF_DAY);
        String hex_hour = ByteUtil.buqi3(Integer.toHexString(hour));
        Integer min = now.get(Calendar.MINUTE);
        String hex_min = ByteUtil.buqi3(Integer.toHexString(min));
        Integer sec = now.get(Calendar.SECOND);
        String hex_sec = ByteUtil.buqi3(Integer.toHexString(sec));


        Integer src0 = Integer.parseInt(src.substring(0, 2), 16);
        Integer src1 = Integer.parseInt(src.substring(2, 4), 16);
        Integer src2 = Integer.parseInt(src.substring(4, 6), 16);
        Integer src3 = Integer.parseInt(src.substring(6, 8), 16);
        Integer src4 = Integer.parseInt(src.substring(8, 10), 16);
        Integer src5 = Integer.parseInt(src.substring(10, 12), 16);

        Integer dest0 = Integer.parseInt(mu.substring(0, 2), 16);
        Integer dest1 = Integer.parseInt(mu.substring(2, 4), 16);
        Integer dest2 = Integer.parseInt(mu.substring(4, 6), 16);
        Integer dest3 = Integer.parseInt(mu.substring(6, 8), 16);
        Integer dest4 = Integer.parseInt(mu.substring(8, 10), 16);
        Integer dest5 = Integer.parseInt(mu.substring(10, 12), 16);


        Integer len = 0;
        String length = "0000";
        String cmd_hex = "03";
        Integer cmd = Integer.parseInt(cmd_hex, 16);


        Integer bb = f1 + f2 + vma + vmi + sec + min + hour + day + month + year + src0 + src1 + src2 + src3 + src4 + src5 + dest0 + dest1 + dest2 + dest3 + dest4 + dest5 + len + cmd;
        Integer check = bb & 0xff;
        byte cc = (byte) check.intValue();
        String crc = ByteUtil.buqi3(toHex(cc));

        String message = headed + flowId + version + hex_sec + hex_min + hex_hour + hex_day + hex_month + hex_year + mu + src + length + cmd_hex + crc + "2323";
        log.info(src + "应答心跳包:" + message);
        return ByteUtil.toBytes(message);
    }

    // 把byte 转化为两位十六进制数
    public static String toHex(byte b) {
        String result = Integer.toHexString(b & 0xFF);
        if (result.length() == 1) {
            result = '0' + result;
        }
        return result;
    }
}
